上一篇已經介紹route,接著以實際專案會用到的api來繼續實作
1.文章資料API規劃
2.取得單一文章資料API開發
3.錯誤處理(Error Handling)
以下為目前文章相關的API
| route | verb | description | 
|---|---|---|
| /posts | POST | 新增文章 | 
| /posts | GET | 取得所有文章 | 
| /posts/:postId | PUT | 更新文章 | 
| /posts/:postId | DELETE | 刪除文章 | 
| /posts/:postId | GET | 取得單一文章內容 | 
我們將以上api都建立在routes/posts-routes.js裡面
🔸這篇只有提到取得文章api的邏輯,其他api會在後面篇章補充。
//posts-routes.js
const express = require('express');
const router = express.Router();
//@router POST /api/posts
//@desc 新增文章
//@access Public
router.post("/", (req,res,next)=>{
    res.json({message: 'It works!'});
});
//@router  GET api/posts
//@desc 取得所有文章
//@access Public
router.get("/",(req,res,next)=>{
    console.log('GET Request');
    res.json({message: 'It works!'});
});
//@router  GET api/posts/:postId
//@desc 取得文章資訊(單一)
//@access Public
router.get("/:postId",(req,res,next)=>{
    console.log('GET Request');
    res.json({message: 'It works!'});
});
//@router PUT /api/posts/:postId
//@desc 更新文章
//@access Public
router.put("/:postId", (req,res,next)=>{
    res.json({message: 'It works!'});
});
//@router DELETE api/posts
//@desc 刪除文章
//@access Public*/
router.delete("/:postId", (req,res,next)=>{
    res.json({message: 'It works!'});
});
module.exports =  router;
postId取得文章資料看到上面的程式,其中編輯、刪除、取得都有一個postId,這個postId就是文章的uid(唯一標識符Unique_identifier),就像身分證是我們國民的uid,不會跟別人重複。
現在我們要修改取得文章資訊的handle function,要透過postId把文章資料取回來。
因為現在沒有連接資料庫,所以在檔案裡面先做一個mock data。
//posts-routes.js
const MOCK_POSTS = [
    {
        id: 'p1',
        title: '文章1',
        tags:['chatGPT'],
        content:'ChatGPT'
    },
    {
        id: 'p2',
        title: '文章2',
        tags:['frontend'],
        content:'Micro frontend'
        
    }
]
...(略)
接著我們修改get 的回傳內容,透過以下的寫法就能取得URL裡面的router parameters
//posts-routes.js
//@router  GET api/posts/:postId
//@desc 取得文章資訊(單一).
//@access Public
router.get("/:postId",(req,res,next)=>{
    //透過req.params取得URL的parameters
    const postId = req.params.postId;  
    //透過postId在我們的假資料尋找對應的文章內容
    const post = MOCK_POSTS.find(post =>{
        return post.id === postId;
    });
    //將找到的文章資料回傳
    res.json({post}); //{post:post}的簡寫
});
關於get parameters的使用方式請參考:Get parameter in Express.js
這時我們在瀏覽器輸入https://localhost:5000/api/post/p1 就可以看到取回來的資料了
剛剛已經成功取回資料了,那當我們輸入不存在的id時會怎麼樣呢?
可以看到會回傳一個空值也就是沒回傳任何東西,但這種不明確的回應會客戶端不曉得是哪裡出了問題。
所以我們要在Get api/posts/:postId裡面加上錯誤處理
//posts-routes.js
//@router  GET api/posts/:postId
//@desc 取得文章資訊(單一).
//@access Public
router.get("/:postId",(req,res,next)=>{
    //透過req.params取得URL的parameters
    const postId = req.params.postId;  
    
    //透過postId在我們的假資料尋找對應的文章內容
    const post = MOCK_POSTS.find(post =>{
        return post.id === postId;
    });
    
    //若文章不存在於假資料(資料庫)
    if(!post){
        return res.status(404).json({ message: '此id的文章不存在'})
    }
    
    //將找到的文章資料回傳
    res.json({post}); //{post:post}的簡寫
});
此時我們在https://localhost:5000/api/post/p3(不存在的文章),就會看到錯誤訊息了。
使用error handling middleware,可以集中處理和管理錯誤,提高程式的可維護性,不需要在每個路由處理程式中都處理相同的錯誤情況(例如:原本可能要在每個route裡面加入console.error()來查看錯誤訊息)
//server.js
const express = require('express');
const app = express();
const port = 5000;
const postRoutes = require('./routes/posts-routes');
app.use('/api/posts',postRoutes);
app.use((err, req, res, next) => {
   
    //將錯誤的堆疊訊息(stack trace)輸出到控制台,以方便進行偵錯
    console.error(err.stack);
    
    res.status(err.status || 500);
    
    res.json({
        error: {
            message: err.message  || 'Internal Server Error'
        }
    });
});
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
}); 
然後我們再回去調整posts-routes.js
//posts-routes.js
//@router  GET api/posts/:postId
//@desc 取得文章資訊(單一).
//@access Public
router.get("/:postId",(req,res,next)=>{
    //透過req.params取得URL的parameters
    const postId = req.params.postId;  
    
    //透過postId在我們的假資料尋找對應的文章內容
    const post = MOCK_POSTS.find(post =>{
        return post.id === postId;
    });
    
    //若文章不存在於假資料(資料庫)
    if(!post){
        const error = new Error('此id的文章不存在');
        error.status = 404;
        return next(error); //會觸發error middleware
    }
    
    //將找到的文章資料回傳
    res.json({post}); 
});

雖然顯示的是相同的錯誤訊息,但這樣作法能讓錯誤處理更乾淨和容易維護~
什麼是RESTful API
Express.js Error Handling
Express.js get parameter